package com.sc.sc250601.cook.service.impl;

import com.sc.sc250601.cook.mapper.CommentMapper;
import com.sc.sc250601.cook.mapper.LikeMapper;
import com.sc.sc250601.cook.mapper.PostMapper;
import com.sc.sc250601.cook.mapper.UserMapper;
import com.sc.sc250601.cook.pojo.*;
import com.sc.sc250601.cook.service.PostService;
import com.sc.sc250601.cook.service.UserFollowService;
import com.sc.sc250601.cook.util.StringRedisTemplateUtil;
import org.apache.ibatis.annotations.Param;
import com.fasterxml.jackson.core.type.TypeReference; // 这是Jackson的类，正确！
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import org.springframework.data.redis.core.script.DefaultRedisScript;
@Service
public class PostServiceImpl implements PostService {
    @Autowired
    PostMapper pm;

    @Autowired
    LikeMapper lm;
    @Autowired
    CommentMapper cm;

    @Autowired
    UserFollowService us;
    // 新增：注入用户Mapper（用于查询作者昵称）
    @Autowired
    UserMapper userMapper;  // 假设你有UserMapper用于查询用户信息
    @Autowired
    StringRedisTemplateUtil stringRedisTemplateUtil;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    // 点赞操作后发送消息
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public List<Post> selectAll() {
        // 1. 反序列化时指定具体泛型类型（List<Post>）
        List<Post> posts = stringRedisTemplateUtil.getObject("AllPosts", new TypeReference<List<Post>>() {});
        if (posts != null) {
//            System.out.println("---------------是走了redies");
            return posts;
        } else {
            posts = pm.selectAll();
            // 2. 存储时确保序列化为JSON数组
            stringRedisTemplateUtil.setObject("AllPosts", posts, 3600);
        }
        return posts;
    }

    public List<Post> selectByUid(List<Long> uids) {
        // 1. 生成稳定的缓存Key（排序+固定分隔符，避免顺序影响）
        String key = generateUidListKey(uids);

        // 2. 反序列化时指定具体泛型类型
        List<Post> postByUid = stringRedisTemplateUtil.getObject(
                key,
                new TypeReference<List<Post>>() {}
        );
        if (postByUid != null) {
//            //遍历集合重新设置点赞数
//            for(int i=0;i<postByUid.size();i++){
//                Long likeCount=stringRedisTemplateUtil.getPostLikeCount(postByUid.get(i).getId());
//                System.out.println("查看存储的--------"+likeCount);
//                postByUid.get(i).setLikeCount(Math.toIntExact(likeCount));
//            }

            return postByUid;
        } else {
            postByUid = pm.selectByUid(uids);
            stringRedisTemplateUtil.setObject(key, postByUid, 3600);
        }
        return postByUid;
    }

    // 辅助方法：生成稳定的List<Long>缓存Key
    private String generateUidListKey(List<Long> uids) {
        if (uids == null || uids.isEmpty()) {
            return "empty_uid_list";
        }
        // 排序确保顺序不影响Key
        List<Long> sortedUids = new ArrayList<>(uids);
        Collections.sort(sortedUids);
        // 用固定分隔符拼接，避免数字拼接歧义（例如1和11 vs 1,11）
        return "uids:" + String.join(",", sortedUids.stream()
                .map(String::valueOf)
                .collect(Collectors.toList()));
    }
    @Transactional(rollbackFor = Exception.class)
    //点赞
    public Result addLikeCount(Like like) {
//        //先查like表，看用户是否有数据，有就-1，没有就+1 且添加like表数据
//        //查看用户是否有点赞记录
//        Like l=lm.selectByUid_Type_LikeID(like);
//        Date happy=pm.selectByPrimaryKey(like.getLikedId()).getUpdateTime();//获取当前的帖子的更新时间作为
//        //乐观锁
//        if(l==null){//没有点赞记录，可以点赞，且添加点赞记录
//
//            int n=pm.addLikeCount(like.getLikedId(),happy);
//            if(n>0){
//                lm.addRecord(like);
//                return new Result(1,"点赞成功",pm.selectLikeCount(like.getLikedId()));
//            }
//            return new Result(0,"点赞失败",pm.selectLikeCount(like.getLikedId()));
//        }else {
//           int n= pm.reduceLikeCount(like.getLikedId(),happy);
//           if(n>0){
//               lm.delRecord(like);
//               return new Result(2,"取消点赞成功",pm.selectLikeCount(like.getLikedId()));
//           }
//            return new Result(0,"取消点赞失败",pm.selectLikeCount(like.getLikedId()));
//        }

        //方法2
        // ... 执行Lua脚本获取result ...
       Integer result= stringRedisTemplateUtil.likeOrCancel(like.getLikedId(),like.getUserId());
        // 发送消息到队列（同步到数据库）
        LikeMessage message = new LikeMessage(like.getLikedId(), like.getUserId(), result==1); // result=1表示点赞，0表示取消
        rabbitTemplate.convertAndSend("like.sync.queue", message);
        Result r=new Result();
        if(result==1){
           r= new Result(1,"点赞成功",stringRedisTemplateUtil.getPostLikeCount(like.getLikedId()));
        }else {
           r= new Result(1,"取消点赞成功",stringRedisTemplateUtil.getPostLikeCount(like.getLikedId()));
        }
        //修改了数据删除缓存
        stringRedisTemplateUtil.deleteByPrefix("uids:");
        stringRedisTemplateUtil.deleteByPrefix("AllPosts");

        return r;

    }
    // 消费者：异步更新数据库
    @RabbitListener(queues = "like.sync.queue")
    public void syncLikeToDb(LikeMessage message) {
        if (message.isLike()) {
            // 点赞：插入post_like表
            lm.insert(new Like(message.getPostId(), message.getUserId(),true));
        } else {
            // 取消点赞：删除post_like表记录
            lm.delRecord(new Like(message.getPostId(), message.getUserId(),true));
        }
        // 同时更新post表的like_count字段（可选，也可通过定时任务批量更新）
        pm.updateLikeCount(message.getPostId(), stringRedisTemplateUtil.getPostLikeCount(message.getPostId()));
    }


    public int addPost(Post p) {
        // 1. 保存新帖子
        int n = pm.insert(p);

        // 2. 新增成功后，推送通知给粉丝
        if (n > 0) {
            // 获取发布者ID（帖子的userId）
            Long authorId = p.getUserId();

            // 获取发布者昵称（用于通知显示）
            String authorName = userMapper.selectByPrimaryKey(authorId).getUsername();  // 需要在UserMapper中实现该方法

            // 获取帖子标题和ID
            String contentTitle = p.getTitle();
            Long contentId = p.getId();  // 注意：如果是自增ID，需要确保insert后已获取到ID

            // 调用用户关注服务，推送通知给所有粉丝

            us.pushNewContentToFans(authorId,authorName, contentTitle, contentId);
        }
        // 2. 第二步：删除相关的缓存（关键）
        // 全量帖子列表缓存已过时，删除
        stringRedisTemplateUtil.delete("AllPosts");

        // 如果有「用户帖子列表缓存」（如uids:3），也需删除（新增的帖子属于某个用户）
        String userPostKey = "uids:" + p.getUserId(); // 对应selectByUid的缓存键
        stringRedisTemplateUtil.delete(userPostKey);

        return n;
    }


    public Post selectById(Long id) {
        //浏览量+1

       // pm.addViewCount(id);
        Post p=stringRedisTemplateUtil.getObject("postById"+id,Post.class);
        incrPostViewCount(id);
        Long count=getPostViewCount(id);
        if(p!=null){
            p.setLikeCount(Math.toIntExact(stringRedisTemplateUtil.getPostLikeCount(id)));
            p.setViewCount(count);
            return p;
        }else {
            p=pm.selectByPrimaryKey(id);
            stringRedisTemplateUtil.setObject("postById"+id,p,3600);
            p.setViewCount(count);
        }

        List<Comment> comments=cm.selectByTargetTypeAndId(id);
        p.setComments(comments);
        return p;
    }
    /**
     * 增加帖子浏览量
     * @param postId 帖子ID
     * @return 增加后的浏览量
     */
    public Long incrPostViewCount(Long postId) {
        String key = "post:view:count:" + postId;
        // INCR 命令：原子自增1，返回自增后的值
        return stringRedisTemplate.opsForValue().increment(key);
    }
    public Long getPostViewCount(Long postId) {
        String key = "post:view:count:" + postId;
        String countStr = stringRedisTemplate.opsForValue().get(key);
        return countStr == null ? 0L : Long.parseLong(countStr);
    }


}
